home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / gs24src.zip / ZFONT0.C < prev    next >
C/C++ Source or Header  |  1991-11-26  |  7KB  |  219 lines

  1. /* Copyright (C) 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* zfont0.c */
  21. /* Composite font creation operator for Ghostscript */
  22. #include "ghost.h"
  23. #include "errors.h"
  24. #include "oper.h"
  25. /*
  26.  * The following lines used to say:
  27.  *    #include "gsmatrix.h"
  28.  *    #include "gxdevice.h"        /. for gxfont.h ./
  29.  * Tony Li says the longer list is necessary to keep the GNU compiler
  30.  * happy, but this is pretty hard to understand....
  31.  */
  32. #include    "gxfixed.h"
  33. #include    "gxmatrix.h"
  34. #include    "gzstate.h"        /* must precede gxdevice */
  35. #include    "gxdevice.h"        /* must precede gxfont */
  36. #include    "gschar.h"
  37. #include "gxfont.h"
  38. #include "alloc.h"
  39. #include "font.h"
  40. #include "dict.h"
  41. #include "name.h"
  42. #include "state.h"
  43. #include "store.h"
  44.  
  45. /* Imports */
  46. extern int build_gs_font(P4(os_ptr, gs_font **, font_type, ref *));
  47. extern ref name_FID;
  48.  
  49. /* Forward references */
  50. private int ensure_char_entry(P4(os_ptr, ref *, byte *, int));
  51.  
  52. /* Names of system-known keys in type 0 font dictionaries: */
  53. private ref name_EscChar;
  54. private ref name_FDepVector;
  55. private ref name_FMapType;
  56. private ref name_PrefEnc;
  57. private ref name_ShiftIn;
  58. private ref name_ShiftOut;
  59. private ref name_SubsVector;
  60. private ref name_Type0BuildChar;
  61.  
  62. /* Initialize the composite font operators */
  63. private void
  64. zfont0_init()
  65. {    static names_def fnd0[] = {
  66.        { "EscChar", &name_EscChar },
  67.        { "FDepVector", &name_FDepVector },
  68.        { "FMapType", &name_FMapType },
  69.        { "PrefEnc", &name_PrefEnc },
  70.        { "ShiftIn", &name_ShiftIn },
  71.        { "ShiftOut", &name_ShiftOut },
  72.        { "SubsVector", &name_SubsVector },
  73.        { "Type0BuildChar", &name_Type0BuildChar },
  74.        names_def_end
  75.     };
  76.     init_names(fnd0);
  77.  
  78.     /* Make the standard BuildChar procedure executable. */
  79.     r_set_attrs(&name_Type0BuildChar, a_executable);
  80. }
  81.  
  82. /* .buildfont0 */
  83. /* Build a type 0 (composite) font. */
  84. int
  85. zbuildfont0(os_ptr op)
  86. {    ref *pfmaptype;
  87.     gs_type0_data data;
  88.     ref *pfdepvector;
  89.     ref *pprefenc;
  90.     ref *psubsvector;
  91.     gs_font *pfont;
  92.     font_data *pdata;
  93.     int i;
  94.     int code;
  95.     check_type(*op, t_dictionary);
  96.     if ( dict_find(op, &name_FMapType, &pfmaptype) <= 0 ||
  97.          !r_has_type(pfmaptype, t_integer) ||
  98.          pfmaptype->value.intval < (int)fmap_type_min ||
  99.          pfmaptype->value.intval > (int)fmap_type_max ||
  100.          dict_find(op, &name_FDepVector, &pfdepvector) <= 0 ||
  101.          !r_has_type(pfdepvector, t_array)
  102.        )
  103.         return e_invalidfont;
  104.     data.FMapType = (fmap_type)pfmaptype->value.intval;
  105.     /* Check that every element of the FDepVector is a font. */
  106.     data.fdep_size = r_size(pfdepvector);
  107.     for ( i = 0; i < data.fdep_size; i++ )
  108.        {    ref *pdep = pfdepvector->value.refs + i;
  109.         ref *pfid;
  110.         gs_font *psub;
  111.         if ( !r_has_type(pdep, t_dictionary) ||
  112.              dict_find(pdep, &name_FID, &pfid) <= 0 ||
  113.              !r_has_type(pfid, t_fontID)
  114.            )
  115.             return e_invalidfont;
  116.         /*
  117.          * Check the inheritance rules.  Allowed configurations
  118.          * (paths from root font) are defined by the regular
  119.          * expression:
  120.          *    (shift | double_escape escape* | escape*)
  121.          *      non_modal* non_composite
  122.          */
  123.         psub = pfid->value.pfont;
  124.         if ( psub->FontType == ft_composite )
  125.            {    fmap_type fmt = psub->data.type0_data.FMapType;
  126.             if ( fmt == fmap_double_escape ||
  127.                  fmt == fmap_shift ||
  128.                  fmt == fmap_escape &&
  129.                   !(data.FMapType == fmap_escape ||
  130.                 data.FMapType == fmap_double_escape)
  131.                )
  132.                 return e_invalidfont;
  133.            }
  134.        }
  135.     switch ( data.FMapType )
  136.        {
  137.     case fmap_escape: case fmap_double_escape:    /* need EscChar */
  138.         code = ensure_char_entry(op, &name_EscChar, &data.EscChar, 255);
  139.         break;
  140.     case fmap_shift:            /* need ShiftIn & ShiftOut */
  141.         code = ensure_char_entry(op, &name_ShiftIn, &data.ShiftIn, 15);
  142.         if ( code == 0 )
  143.           code = ensure_char_entry(op, &name_ShiftOut, &data.ShiftOut, 14);
  144.         break;
  145.     case fmap_SubsVector:            /* need SubsVector */
  146.         if ( dict_find(op, &name_SubsVector, &psubsvector) <= 0 ||
  147.              !r_has_type(psubsvector, t_string) ||
  148.              r_size(psubsvector) == 0 ||
  149.              (data.subs_width = (int)*psubsvector->value.bytes + 1) > 4 ||
  150.              (r_size(psubsvector) - 1) % data.subs_width != 0
  151.            )
  152.             return e_invalidfont;
  153.     default:
  154.         code = 0;
  155.        }
  156.     if ( code < 0 ) return code;
  157.     code = build_gs_font(op, &pfont, ft_composite, &name_Type0BuildChar);
  158.     if ( code != 0 ) return code;
  159.     if ( dict_find(op, &name_PrefEnc, &pprefenc) <= 0 )
  160.        {    ref nul;
  161.         make_null_new(&nul);
  162.         if ( (code = dict_put(op, &name_PrefEnc, &nul)) < 0 )
  163.             return code;
  164.        }
  165.     /* Fill in the font data */
  166.     pdata = (font_data *)(pfont->client_data);
  167.     data.subs_size = (r_size(psubsvector) - 1) / data.subs_width;
  168.     data.SubsVector = psubsvector->value.bytes + 1;
  169.     data.encoding_size = r_size(&pdata->Encoding);
  170.     data.Encoding =
  171.       (uint *)alloc(data.encoding_size, sizeof(uint),
  172.                "buildfont0(Encoding)");
  173.     /* Fill in the encoding vector, checking to make sure that */
  174.     /* each element is an integer between 0 and fdep_size-1. */
  175.     for ( i = 0; i < data.encoding_size; i++ )
  176.        {    ref *penc = pdata->Encoding.value.refs + i;
  177.         if ( !r_has_type(penc, t_integer) ||
  178.              (ulong)penc->value.intval >= data.fdep_size
  179.            )
  180.             return e_invalidfont;
  181.         data.Encoding[i] = (uint)penc->value.intval;
  182.        }
  183.     data.FDepVector =
  184.       (gs_font **)alloc(data.fdep_size, sizeof(gs_font *),
  185.                "buildfont0(FDepVector)");
  186.     for ( i = 0; i < data.fdep_size; i++ )
  187.        {    ref *pfid;
  188.         /* The lookup can't fail, because of the pre-check above. */
  189.         dict_find(pfdepvector->value.refs + i, &name_FID, &pfid);
  190.         data.FDepVector[i] = pfid->value.pfont;
  191.        }
  192.     pfont->data.type0_data = data;
  193.     return 0;
  194. }
  195. /* Private routine to find or add an integer entry in a font dictionary. */
  196. private int
  197. ensure_char_entry(os_ptr op, ref *pname, byte *pvalue, int default_value)
  198. {    ref *pentry;
  199.     if ( dict_find(op, pname, &pentry) <= 0 )
  200.        {    ref ent;
  201.         make_int(&ent, default_value);
  202.         return dict_put(op, pname, &ent);
  203.        }
  204.     else
  205.       if ( !r_has_type(pentry, t_integer) ||
  206.            (ulong)(pentry->value.intval) > 255
  207.          )
  208.         return e_invalidfont;
  209.     *pvalue = (byte)pentry->value.intval;
  210.     return 0;
  211. }
  212.  
  213. /* ------ Initialization procedure ------ */
  214.  
  215. op_def zfont0_op_defs[] = {
  216.     {"1.buildfont0", zbuildfont0},
  217.     op_def_end(zfont0_init)
  218. };
  219.